package com.xaicode.auth.config.redisson;

import cn.hutool.core.util.StrUtil;
import io.netty.channel.nio.NioEventLoopGroup;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.Codec;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.config.ClusterServersConfig;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.redisson.spring.cache.CacheConfig;
import org.redisson.spring.cache.RedissonSpringCacheManager;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.util.*;

@EnableCaching
@Configuration(value = "redissonConfig")
public class RedissonConfig {

    @Resource
    private RedissonProperties redissonProperties;


    @Bean(destroyMethod = "shutdown")
    @ConditionalOnMissingBean(RedissonClient.class)
    public RedissonClient redisson() {
        Config config = new Config();
        Codec codec = new JsonJacksonCodec();
        config.setCodec(codec);
        config.setThreads(redissonProperties.getThread());
        config.setEventLoopGroup(new NioEventLoopGroup());

        // 有集群会优先使用集群
        if (StrUtil.isNotBlank(redissonProperties.getClusterNodeAddress())) {

            // 整理集群节点
            String[] nodes = redissonProperties.getClusterNodeAddress().split(",");
            List<String> newNodes = new ArrayList<>(nodes.length);
            Arrays.stream(nodes).forEach((node) ->
                    newNodes.add(node.startsWith("redis://") ? node : "redis://" + node));

            ClusterServersConfig cluster = config.useClusterServers();
            cluster.addNodeAddress(newNodes.toArray(new String[0]));
            cluster.setScanInterval(redissonProperties.getClusterScanInterval());
            cluster.setMasterConnectionPoolSize(redissonProperties.getMasterConnectionPoolSize());
            cluster.setMasterConnectionMinimumIdleSize(redissonProperties.getMasterConnectionMinimumIdleSize());
            cluster.setSlaveConnectionPoolSize(redissonProperties.getSlaveConnectionPoolSize());
            cluster.setSlaveConnectionMinimumIdleSize(redissonProperties.getSlaveConnectionMinimumIdleSize());

            cluster.setSubscriptionConnectionMinimumIdleSize(redissonProperties.getSubscriptionConnectionMinimumIdleSize());
            cluster.setSubscriptionConnectionPoolSize(redissonProperties.getSubscriptionConnectionPoolSize());
            cluster.setSubscriptionsPerConnection(redissonProperties.getSubscriptionsPerConnection());
            cluster.setIdleConnectionTimeout(redissonProperties.getIdleConnectionTimeout());
            cluster.setClientName(redissonProperties.getClientName());
            cluster.setRetryAttempts(redissonProperties.getRetryAttempts());
            cluster.setRetryInterval(redissonProperties.getRetryInterval());
            cluster.setTimeout(redissonProperties.getTimeout());
            cluster.setConnectTimeout(redissonProperties.getConnectTimeout());
            if (StrUtil.isNotBlank(redissonProperties.getPassword())) {
                cluster.setPassword(redissonProperties.getPassword());
            }
        } else {
            // 单节点模式
            SingleServerConfig single = config.useSingleServer();
            single.setAddress(redissonProperties.getAddress());
            single.setDatabase(redissonProperties.getDatabase());
            single.setConnectionPoolSize(redissonProperties.getConnectionPoolSize());
            single.setConnectionMinimumIdleSize(redissonProperties.getConnectionMinimumIdleSize());
            single.setDnsMonitoringInterval(redissonProperties.getDnsMonitoringInterval());

            single.setSubscriptionConnectionMinimumIdleSize(redissonProperties.getSubscriptionConnectionMinimumIdleSize());
            single.setSubscriptionConnectionPoolSize(redissonProperties.getSubscriptionConnectionPoolSize());
            single.setSubscriptionsPerConnection(redissonProperties.getSubscriptionsPerConnection());
            single.setIdleConnectionTimeout(redissonProperties.getIdleConnectionTimeout());
            single.setClientName(redissonProperties.getClientName());
            single.setRetryAttempts(redissonProperties.getRetryAttempts());
            single.setRetryInterval(redissonProperties.getRetryInterval());
            single.setTimeout(redissonProperties.getTimeout());
            single.setConnectTimeout(redissonProperties.getConnectTimeout());
            if (StrUtil.isNotBlank(redissonProperties.getPassword())) {
                single.setPassword(redissonProperties.getPassword());
            }
        }
        return Redisson.create(config);
    }

    @Bean
    @ConditionalOnMissingBean(CacheManager.class)
    CacheManager cacheManager(RedissonClient redissonClient) {
        Map<String, CacheConfig> config = new HashMap<>();
        // create cache with ttl = 24 minutes and maxIdleTime = 12 minutes
        config.put("ASL_CLOUD_CACHE", new CacheConfig(24 * 60 * 1000, 12 * 60 * 1000));
        return new RedissonSpringCacheManager(redissonClient, config);
    }

}
